package com.cskaoyan.javase.object._1getclass;

import com.sun.media.jfxmedia.events.NewFrameEvent;

/**
 * getClass方法
 * 1.方法的声明:
 *      public final native Class<?> getClass();
 *      final表示该方法无法被重写
 *      native表示它是一个本地方法,没有方法体
 *      Class<?>是返回值类型,表示该方法返回Class对象
 *          <?>这是泛型,今天我们先不管它
 *          Java的泛型仅在程序的编译时期生效,不影响程序执行
 *
 * 2.方法的作用:
 *      获取Class对象
 *      那么什么是Class类,什么是Class对象?
 *      文档中:
 *      Class 类的实例表示正在运行的 Java 应用程序中的类和接口。
 *      Class对象是某个类/接口的运行时对象
 *
 * 3,什么是运行时类/接口对象?
 *      JVM通过类加载的过程,了解和认识了某个类型
 *      但是程序在运行时期,程序员对某个类的类型信息是一无所知的
 *      但是这种在运行时期,获取类型信息,对于程序员是很重要的
 *          这会让程序员能够在程序的运行期间,动态的获取类型信息,动态的完成一些操作
 *
 *      那么以上需求,是可以完成的
 *      JVM在类加载的某个类的时候(在加载的步骤中)会在堆上创建一个封装了该类类型信息的
 *      对象,称之为某个类/接口的运行时对象,也就是Class对象
 *
 *      什么是Class对象?
 *      封装了某个类/接口,类型信息的对象
 *
 *      程序员通过获取Class对象,就能够在程序的运行期间,获取类型信息,完成相应操作
 *      而getClass方法就是获取类的Class对象的一种方式(不是常用方式)
 *
 * 4.Class对象的注意事项:
 *      a.Class对象是怎么来的?
 *          注意不是getClass方法创建的,而是类加载过程中JVM创建的
 *          getClass方法无非是用一个引用指向Class对象,让我们能够使用Class对象
 *
 *      b.某个类的Class对象有几个?
 *          类加载只有一次,所以某个类的Class对象,也只有一个
 *
 *      c.某个类不同对象,分别调用getClass,然后"=="比较,结果是什么?
 *          是true,因为某个类的Class对象唯一
 *
 *      d.不同类的不同对象,分别调用getClass,然后"=="比较,结果是什么?
 *          肯定是false,不同类的Class对象肯定不同.
 *
 *      根据以上c和d的特点,getClass方法,可以用来判断两个引用所指向的对象,是不是同种对象.(比如判断是不是都是Student对象)
 *
 * 扩展:
 *      Class对象的用途
 *      获取了Class对象,就是获取了某个类的类型信息
 *      这样就可以在程序的运行期间,对一个类做动态操作
 *      这就是Java中的反射技术,配合反射破解私有权限,反射是可以对一个类"为所欲为"
 *      所以反射其实非常简单,就是Class类的API 就是调用该类的方法
 *
 * @since 10:44
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student();
        Student s2 = new Student();
        Class stuClazz = s.getClass();
        Class stuClazz2 = s2.getClass();
        System.out.println(stuClazz == stuClazz2);

        Teacher t = new Teacher();
        Class teacherClazz = t.getClass();
        System.out.println(teacherClazz == stuClazz);

        System.out.println("-----------------------------------");
        System.out.println(judgeObjectType(s, s2));
        System.out.println(judgeObjectType(t, s));

        System.out.println("--------------------------------");
        System.out.println(teacherClazz.getName());
        System.out.println(teacherClazz.getSimpleName());
    }

    // true表示两个引用的对象是同种对象,反之则不是
    public static boolean judgeObjectType(Object o1, Object o2) {
        /*Class o1Clazz = o1.getClass();
        Class o2Clazz = o2.getClass();
        return o1Clazz == o2Clazz;*/
        return o1.getClass() == o2.getClass();
    }
}

class Student {
}

class Teacher {

}